package cn.edu.zut.mock;

import cn.edu.zut.bean.OrderInfo;
import com.github.javafaker.Faker;

import java.sql.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class OrderInfoDataGenerator {

    private static final String DB_URL = "jdbc:mysql://hadoop102:3306/driver?allowPublicKeyRetrieval=true&useSSL=false&requireSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "000000";
    private static final int BATCH_SIZE = 100;

    // 缓存 passenger_ids 和 driver_id -> car_id 映射
    private static List<String> passengerIds = null;

    public static void main(String[] args) {
        // 每次运行追加10条数据
        int count = 10;
        generateData(count);
    }

    public static void generateData(int count) {
        Faker faker = new Faker(Locale.CHINA);
        List<OrderInfo> orders = new ArrayList<>();

        List<OrderDetailRecord> details = getOrderDetailsFromDatabase(count);
        if (details.isEmpty()) {
            throw new IllegalStateException("order_detail 表中没有可用数据，请先运行 OrderDetailDataGenerator");
        }

        if (passengerIds == null || passengerIds.isEmpty()) {
            passengerIds = getAllPassengerIds();
        }

        if (passengerIds.isEmpty()) {
            throw new IllegalStateException("passenger 表中没有可用的 passenger_id");
        }

        // 获取数据库中已有的最大order_id
        long startId = getMaxOrderId() + 1;

        for (int i = 0; i < count && i < details.size(); i++) {
            OrderDetailRecord detail = details.get(i);

            LocalDateTime pickupTime = toLocalDateTime(detail.pickupTime);
            LocalDateTime startTime = randomStartTimeAfterPickup(faker, pickupTime);
            LocalDateTime endTime = randomEndTimeAfterStartTime(faker, startTime);

            String passengerId = getRandomPassengerId(faker);
            String carId = getCarIdByDriverId(detail.driverId);

            if (carId == null) {
                System.err.println("司机ID: " + detail.driverId + " 没有对应的 car_id");
                continue;
            }

            OrderInfo order = OrderInfo.builder()
                    .order_id(String.valueOf(startId + i)) // 从最大order_id加1开始
                    .city_id("1") // 可以扩展为随机城市
                    .passenger_id(passengerId)
                    .driver_id(detail.driverId)
                    .car_id(carId)
                    .start_time(startTime)
                    .end_time(endTime)
                    .total_price(detail.totalPrice)
                    .status(detail.status)
                    .build();

            orders.add(order);
        }

        insertIntoDatabase(orders);
    }

    /**
     * 从 order_detail 表中读取订单明细数据
     */
    private static List<OrderDetailRecord> getOrderDetailsFromDatabase(int limit) {
        List<OrderDetailRecord> result = new ArrayList<>();
        String query = "SELECT order_id, driver_id, pickup_time, total_price, status FROM order_detail ORDER BY RAND() LIMIT " + limit;

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            while (rs.next()) {
                String orderId = rs.getString("order_id");
                String driverId = rs.getString("driver_id");
                Timestamp pickupTimeTs = rs.getTimestamp("pickup_time");
                double totalPrice = rs.getDouble("total_price");
                int status = rs.getInt("status");

                result.add(new OrderDetailRecord(orderId, driverId, pickupTimeTs, totalPrice, status));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 获取随机 passenger_id
     */
    private static String getRandomPassengerId(Faker faker) {
        return passengerIds.get(faker.random().nextInt(passengerIds.size()));
    }

    /**
     * 获取 passenger 表中所有 passenger_id
     */
    public static List<String> getAllPassengerIds() {
        List<String> ids = new ArrayList<>();
        String query = "SELECT passenger_id FROM passenger";

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            while (rs.next()) {
                ids.add(rs.getString("passenger_id"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return ids;
    }

    /**
     * 根据 driver_id 获取 car_id
     */
    public static String getCarIdByDriverId(String driverId) {
        String query = "SELECT car_id FROM car WHERE driver_id = ?";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(query)) {

            pstmt.setString(1, driverId);
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    return rs.getString("car_id");
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将 java.util.Date 转换为 java.time.LocalDateTime
     */
    private static LocalDateTime toLocalDateTime(Timestamp date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 生成 start_time，晚于 pickup_time
     */
    private static LocalDateTime randomStartTimeAfterPickup(Faker faker, LocalDateTime pickupTime) {
        long minutesToAdd = faker.number().numberBetween(1L, 30L);
        return pickupTime.plusMinutes(minutesToAdd);
    }

    /**
     * 生成 end_time，晚于 start_time，但不晚于当前时间
     */
    private static LocalDateTime randomEndTimeAfterStartTime(Faker faker, LocalDateTime startTime) {
        long minutesToAdd = faker.number().numberBetween(5L, 120L);
        LocalDateTime endTime = startTime.plusMinutes(minutesToAdd);
        return endTime.isAfter(LocalDateTime.now()) ? LocalDateTime.now() : endTime;
    }

    /**
     * 插入到 order_info 表
     */
    private static void insertIntoDatabase(List<OrderInfo> orders) {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            conn.setAutoCommit(false);
            String sql = "INSERT INTO order_info (order_id, city_id, passenger_id, driver_id, car_id, start_time, end_time, total_price, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";

            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
                for (int i = 0; i < orders.size(); i++) {
                    OrderInfo o = orders.get(i);
                    pstmt.setString(1, o.getOrder_id());
                    pstmt.setString(2, o.getCity_id());
                    pstmt.setString(3, o.getPassenger_id());
                    pstmt.setString(4, o.getDriver_id());
                    pstmt.setString(5, o.getCar_id());
                    pstmt.setTimestamp(6, Timestamp.valueOf(o.getStart_time()));
                    pstmt.setTimestamp(7, Timestamp.valueOf(o.getEnd_time()));
                    pstmt.setDouble(8, o.getTotal_price());
                    pstmt.setInt(9, o.getStatus());

                    pstmt.addBatch();

                    if ((i + 1) % BATCH_SIZE == 0 || i == orders.size() - 1) {
                        pstmt.executeBatch();
                    }
                }
                conn.commit();
                System.out.println("成功插入" + orders.size() + "条订单信息");
            } catch (SQLException e) {
                conn.rollback();
                e.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询数据库中已有的最大order_id
     */
    private static long getMaxOrderId() {
        String sql = "SELECT MAX(CAST(order_id AS SIGNED)) FROM order_info";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {
            if (rs.next()) {
                return rs.getLong(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0; // 如果表为空，返回0
    }

    /**
     * 内部类保存 order_detail 数据
     */
    private static class OrderDetailRecord {
        String orderId;
        String driverId;
        Timestamp pickupTime;
        double totalPrice;
        int status;

        public OrderDetailRecord(String orderId, String driverId, Timestamp pickupTime, double totalPrice, int status) {
            this.orderId = orderId;
            this.driverId = driverId;
            this.pickupTime = pickupTime;
            this.totalPrice = totalPrice;
            this.status = status;
        }
    }
}